package com.theartofdev.edmodo.cropper;

import ohos.agp.components.Component;
import ohos.agp.render.Canvas;
import ohos.agp.render.Paint;
import ohos.agp.render.PixelMapHolder;
import ohos.app.Context;
import ohos.media.image.PixelMap;

/**
 * @Author Zhao BaiYi
 *
 * 这是一个类，图片工具类
 *
 * 此类具有一个component，此component用来显示图片，需要一个PixelMap来进行展示
 *
 * 此component提供了图片的旋转与翻转功能
 *
 * 此类可以进行图片的位置的获取，以及图片的旋转等等功能
 *
 */

public class CropImageView{

    //定义一个component用来显示图片
    private Component mPicture;

    //定义一个最初始的位图
    private PixelMap mPixelMap;

    //记录一个context
    private Context mContext;

    //记录图片的id
    private int mId;

    //上边距
    private int topIndex;

    //位图高宽比(加载长方形图片时使用 此版本不用)
    private float pixelRatio;

    //屏幕高宽比(加载长方形图片时使用 此版本不用)
    private float windowRatio;

    /**
     * 旋转的方向
     * 若图片为正常的垂直方向则为true，否则为false
     * (加载长方形图片时使用 此版本不用)
     * */
    private boolean rotateDirection = true;

    //bitmaputils工具类
    private PixelMapUtils pixelMapUtils;

    /**
     * 设置一个记录所有的点击动作的数组
     * 这样就可以根据每个动作来执行不同个的操作
     * */
    private int[] action;

    //设置一个对外公开的点击动作数组
    public static int[] actionResult;

    //点击动作行为去反，因为canvas反向执行
    private int[] actionReverse;

    //点击动作总次数
    private int actionIndex;

    //公开的供外部调用的点击动作的总次数
    public static int actionIndexResult;

    //CropWindowHandler工具类
    private CropWindowHandler mCropWindowHandler;

    //pixelmapholder
    private PixelMapHolder originalPixelMapHolder;

    //画笔
    private Paint mint;

    //构造函数，用来初始化此Component
    public CropImageView(PixelMap pixelMap , Context context , int id , int top){

        //最原始的图片解码出来的位图
        mPixelMap = pixelMap;

        //保存一个上下文环境
        mContext = context;

        //原始图片的id
        mId = id;

        //图片加载的上边距
        topIndex = top;

        //点击动作总个数（旋转、翻转等）
        actionIndex = 0;

        //对外开放的一个点击动作总个数（旋转、翻转等）
        actionIndexResult = 0;

        //记录动作的数组
        action = new int[10000];

        //初始化图片
        init();
    }

    //初始化
    private void init(){

        //初始化component
        mPicture = new Component(mContext);

        //PixelMapHolder&画笔
        originalPixelMapHolder = new PixelMapHolder(mPixelMap);
        mint = new Paint();

        //初始化工具类
        pixelMapUtils = new PixelMapUtils(mContext , mPixelMap ,400 , mId );
        mCropWindowHandler = new CropWindowHandler(mContext);

        //画图，给图片增加drawtask方法
        mPicture.addDrawTask(drawImage());
    }

    /**
     * 抽离DrawTask方法
     * 此方法綁定在一个component上面
     * 此方法是用来画图像，以及图像的旋转、翻转方法
     * @return 返回一个DrawTask方法
     */
    private Component.DrawTask drawImage(){
        //DrawTask
        Component.DrawTask drawPic = new Component.DrawTask() {
            @Override
            public void onDraw(Component component, Canvas canvas) {
                //获得倒序的动作数组，因为canvas是倒序执行的

                //actionReverse是自己用的
                //actionResult为公开出去的点击动作数组
                actionReverse = new int[actionIndex];
                actionResult = new int[actionIndex];
                for(int i = 0 ; i < actionIndex ; i++){
                    actionReverse[i] = action[actionIndex - i - 1];
                    actionResult[i] = action[actionIndex - i - 1];
                }

                /**
                 * 开始依次执行动作
                 * 根据已经预先约定好的
                 * 1表示旋转
                 * 2表示水平翻转
                 * 3表示垂直翻转
                 * */
                for(int i = 0 ; i < actionIndex ; i++){
                    if(actionReverse[i] == 1){
                        //rotate图像
                        rotate(canvas);
                    }else if(actionReverse[i] == 2){
                        //rotate图像
                        horizontalFilp(canvas);
                    }else if(actionReverse[i] == 3){
                        //rotate图像
                        verticalFilp(canvas);
                    }
                }

                //将图片缩放到屏幕宽度
                canvas.scale((float)mCropWindowHandler.getWindowWidth()/(float) pixelMapUtils.getRealPixelMapWidth() , (float)mCropWindowHandler.getWindowWidth()/(float) pixelMapUtils.getRealPixelMapWidth());

                //画图片
                canvas.drawPixelMapHolder(originalPixelMapHolder,0,0, mint);
            }
        };

        return drawPic;
    }

    //旋转方法
    private void rotate(Canvas canvas){
        /**
         * 以图片正中心（即宽度一半，高度一半）旋转
         * 因为图片已经被放大为屏幕宽度
         * 所以即为屏幕宽度的一半
         * */
        canvas.rotate(90 , mCropWindowHandler.getWindowWidth()/2 , mCropWindowHandler.getWindowWidth()/2);
    }

    //水平翻转方法
    private void horizontalFilp(Canvas canvas){
        /**
         * 水平翻转的方法为先向x轴负方向缩放一倍
         * 然后再沿x轴正方向平移回来
         * */

        //保存
        canvas.save();
        //向下移动高度
        canvas.translate(mCropWindowHandler.getWindowWidth() , 0);
        //向y轴负方向缩放一倍
        canvas.scale(-1f , 1f);
    }

    //竖直翻转方法
    private void verticalFilp(Canvas canvas){
        //保存
        canvas.save();
        //向下移动高度
        canvas.translate(0 , mCropWindowHandler.getWindowWidth());
        //向y轴负方向缩放一倍
        canvas.scale(1f , -1f);
    }

    //旋转方法（外部調用）
    public void rotateOnce(){
        //记录点击动作的数组存进去一个1
        action[actionIndex] = 1;

        //记录点击动作的总动作数目加一
        actionIndex++;
        actionIndexResult++;

        //刷新画布
        mPicture.invalidate();
    }

    //水平翻转（外部調用）
    public void horizontalFilp(){
        //记录点击动作的数组存进去一个2
        action[actionIndex] = 2;

        //记录点击动作的总动作数目加一
        actionIndex++;
        actionIndexResult++;

        //刷新画布
        mPicture.invalidate();
    }

    //竖直翻转（外部調用）
    public void verticalFilp(){
        //记录点击动作的数组存进去一个3
        action[actionIndex] = 3;

        //记录点击动作的总动作数目加一
        actionIndex++;
        actionIndexResult++;

        //刷新画布
        mPicture.invalidate();
    }

    /**
     * 返回一个component实例
     * 这个component已经设置了画图片的方法
     * 这个component设置了图片的旋转以及水平翻转的方法
     * @return Component
     */
    public Component getmPicture(){
        return mPicture;
    }

    //对所有的外部公开一个点击动作数组 以便调用
    public static int[] getActionResult(){
        return actionResult;
    }

    //对所有的外部公开一个点击动作数组的总个数 以便调用
    public static int getActionIndexResult(){
        return actionIndexResult;
    }

}
